package com.airshare;

import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.InetAddress;
import java.net.Socket;


public class FileClient implements FSConstants {
	
	private Socket sock;
	private DataInputStream dis;
	private DataOutputStream dos;
	private ShareDir shareDirectory; // This is where incoming files will be saved
	private String username;
	private InetAddress server;
	private int port;
	private boolean connected = false;

	public FileClient() {
		
	}
	
	public FileClient(String user, ShareDir shareDir, InetAddress server, int port) {
		username = user;
		this.server = server;
		this.port = port;
		this.shareDirectory = shareDir;
	}

	public void connect() {	
		try {
			sock = new Socket(server, port);
			dis = new DataInputStream(sock.getInputStream());
			dos = new DataOutputStream(sock.getOutputStream());
		} catch (IOException e) {
			e.printStackTrace();
		}
		FSMessage msg = new FSMessage();
		msg._srcUser = username;
		msg._messageType = REQ_HELLO;
		FileClient.this.sendMessageToServer(msg);
		getServerReply();
		
		connected = true;
	}

	public void disconnect() {
			try {
				sock.close();
				connected = false;
			} catch (IOException e) {
				e.printStackTrace();
			}
	}

	public boolean isConnected() {
		return connected;
	}
	
	public String getIndex() {
		
		if (!connected) {
			return "";
		}
		
		String index = null;
		FSMessage msg = new FSMessage();
		msg._srcUser = username;
		msg._messageType = REQ_INDEX_SIZE;
		FileClient.this.sendMessageToServer(msg);
				
		FSMessage reply = FileClient.this.getServerReply();
		
		if (reply == null || reply._messageType != RES_INDEX_SIZE) {
			System.err.println("C: Error getting index size from server!" + reply);
		}
				
		int indexSize = reply._indexSize;
		
		msg._messageType = REQ_INDEX;
		sendMessageToServer(msg);
				
		// Manually read index message
		byte[] indexData = new byte[indexSize];
		try {
			dis.read(indexData);
		}
		catch (Exception e) {
			System.err.println("C: Error receiving index data!");
			e.printStackTrace();
		}
		
		try {
			index = (String)(FSUtil.bytesToObject(indexData));
		} catch (IOException e) {
			e.printStackTrace();
		} catch (ClassNotFoundException e) {
			e.printStackTrace();
		}
		return index;	
	}

	// Download a file from the server into the shareDirectory
	public void getFile(String fileName) {
		
		if (!connected) {
			return;
		}
		
		FSMessage msg = new FSMessage();
		msg._fileName = fileName;
		msg._messageType = REQ_FILE_SIZE;
		msg._srcUser = username;
		
		this.sendMessageToServer(msg);
		FSMessage reply = this.getServerReply();
		
		long fileSize = reply._fileSize;
		System.out.println("File size is "+ fileSize);
		// TODO: check if file fits in current share directory
		
		msg._messageType = REQ_FILE;
		msg._fileName = fileName;
		
		this.sendMessageToServer(msg);
		
		shareDirectory.receiveFile(dis, fileName, fileSize);

		// hack: stream gets corrupted after transferring a file!
		disconnect();
		connect();
	}
	
	private FSMessage getServerReply() {
		
		if (!connected) {
			return null;
		}
		
		byte[] data;
		data = new byte[MAX_MESSAGE_SIZE];
		FSMessage msg = null;
		
		try {
			dis.read(data);
			msg = (FSMessage)(FSUtil.bytesToObject(data));
		}
		catch (java.net.SocketException se) {
			System.out.println("server disconnected!");
		}
		catch(Exception e){
			e.printStackTrace();
		}
		return msg;
	}
	
	private void sendMessageToServer(FSMessage msg) {
		
		if (!connected) {
			return;
		}
		
		try {
			byte [] data = FSUtil.objectToBytes(msg);
			dos.write(data);
			dos.flush();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
}
